package com.techsen.tsweb.sys.web.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.techsen.tsweb.core.domain.JsonResult;
import com.techsen.tsweb.core.util.JsonUtil;
import com.techsen.tsweb.core.util.TreeUtil;
import com.techsen.tsweb.core.util.ValidUtil;
import com.techsen.tsweb.core.util.sql.Pager;
import com.techsen.tsweb.sys.domain.Acl;
import com.techsen.tsweb.sys.domain.Menu;
import com.techsen.tsweb.sys.domain.Oper;
import com.techsen.tsweb.sys.domain.Role;
import com.techsen.tsweb.sys.domain.User;
import com.techsen.tsweb.sys.domain.UserRole;
import com.techsen.tsweb.sys.security.ResourceNode;
import com.techsen.tsweb.sys.service.AclService;
import com.techsen.tsweb.sys.service.MenuService;
import com.techsen.tsweb.sys.service.OperService;
import com.techsen.tsweb.sys.service.ResourceService;
import com.techsen.tsweb.sys.service.RoleService;
import com.techsen.tsweb.sys.service.UserRoleService;
import com.techsen.tsweb.sys.service.UserService;

@Controller
@RequestMapping("/sys/role")
public class RoleController {

    @Resource
    private RoleService roleService;
    
    @Resource
    private UserService userService;
    
    @Resource
    private UserRoleService userRoleService;
    
    @Resource
    private MenuService menuService;
    
    @Resource
    private OperService operService;
    
    @Resource
    private AclService aclService;
    
    @Resource
    private ResourceService resourceService;
    
    /**
     * 进入角色管理界面
     */
    @RequestMapping
    public String index(String menuId, Model model) {
        model.addAttribute("menuId", menuId);
        return "sys/role";
    }
    
    /**
     * 分页查询角色
     */
    @RequestMapping("/pager")
    public @ResponseBody Pager<Role> pager(@RequestBody Pager<Role> pager) {
        return this.roleService.findByPager(pager);
    }
    
    /**
     * 进入添加角色界面
     */
    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String add() {
        return "sys/role-add";
    }
    
    /**
     * 添加角色
     */
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public @ResponseBody JsonResult add(Role role) {
        this.roleService.add(role);
        return new JsonResult(role);
    }
    
    /**
     * 删除角色
     */
    @RequestMapping("/delete")
    public @ResponseBody JsonResult delete(String id) {
        this.roleService.delete(id);
        return new JsonResult(id);
    }
    
    /**
     * 进入修改角色界面
     */
    @RequestMapping(value = "/update", method = RequestMethod.GET)
    public String update(String roleId, Model model) {
        Role role = this.roleService.get(roleId);
        model.addAttribute("role", role);
        return "sys/role-update";
    }
    
    /**
     * 修改角色
     */
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public @ResponseBody JsonResult update(Role role) {
        this.roleService.update(role);
        return new JsonResult(role);
    }
    
    /**
     * 根据角色名查询角色
     */
    @RequestMapping("/roles-like-name")
    public @ResponseBody List<Role> rolesLikeName(
            @RequestParam(value = "q", required = false) String roleName) {
        return this.roleService.getRolesLikeName(roleName);
    }
    
    /*-----------------*/
    
    /**
     * 分配角色
     */
    @RequestMapping(value = "/assignuser", method = RequestMethod.GET)
    public String assignuser(String roleId, Model model) {
        if (ValidUtil.isValid(roleId)) {
            model.addAttribute("roleId", roleId);
            
            List<User> users = this.userService.findAll();
            model.addAttribute("users", users);
            
            List<String> assignedIds = UserRole.getUserIdsByUserRoles(this.userRoleService.getListByEntity(new UserRole().setRoleId(roleId)));
            model.addAttribute("assignedIds", JsonUtil.toJson(assignedIds));
        }
        return "sys/role-assignuser";
    }
    
    /**
     * 分配角色
     */
    @RequestMapping(value = "/assignuser", method = RequestMethod.POST)
    public @ResponseBody JsonResult assignrole(
            @RequestParam(value = "roleId", required = false) String roleId,
            @RequestParam(value = "userIds[]", required = false) List<String> userIds) {
        List<UserRole> userroles = new ArrayList<UserRole>();
        if (ValidUtil.isValid(userIds)) {
            for (String userId : userIds) {
                UserRole userrole = new UserRole().setUserId(userId).setRoleId(roleId);
                userroles.add(userrole);
            }
        }
        this.userRoleService.deleteByRoleId(roleId);
        this.userRoleService.batchAdd(userroles);
        return new JsonResult(userroles);
    }
    
    /**
     * 角色授权
     */
    @RequestMapping(value = "/roleauth", method = RequestMethod.GET)
    public String roleauth(String roleId, Model model) {
        if (ValidUtil.isValid(roleId)) {
            model.addAttribute("roleId", roleId);
            
            List<ResourceNode> resources = ResourceNode.convert(this.resourceService.findAll());
            Map<String, List<String>> authedIds = this.resourceService.getResourceIdsByRoleId(roleId);
            if (ValidUtil.isValid(resources)) {
                if (ValidUtil.isValid(authedIds)) {
                    for (ResourceNode node : resources) {
                        List<String> ids = authedIds.get(node.getResourceType());
                        node.setChecked(ValidUtil.isValid(ids) && ids.contains(node.getId()));
                    }
                }
                model.addAttribute("resources", TreeUtil.toTree(resources));
            }
        }
        return "sys/role-roleauth";
    }
    
    /**
     * 角色授权
     */
    @RequestMapping(value = "/roleauth", method = RequestMethod.POST)
    public @ResponseBody JsonResult roleauth(
            @RequestParam(value = "roleId", required = false) String roleId,
            @RequestParam(value = "menuIds[]", required = false) List<String> menuIds,
            @RequestParam(value = "operIds[]", required = false) List<String> operIds) {
        
        List<Acl> acls = new ArrayList<Acl>();
        if (ValidUtil.isValid(menuIds)) {
            List<Menu> menus = this.menuService.getByIds(menuIds);
            Map<String, Integer> aclCodes = new HashMap<String, Integer>();
            for (Menu menu : menus) {
                if (aclCodes.containsKey(menu.getResourceGroup())) {
                    Integer old = aclCodes.get(menu.getResourceGroup());
                    aclCodes.put(menu.getResourceGroup(), old | menu.getAclCode());
                } else {
                    aclCodes.put(menu.getResourceGroup(), menu.getAclCode());
                }
            }
            for (String resourceGroup : aclCodes.keySet()) {
                Integer aclCode = aclCodes.get(resourceGroup);
                Acl acl = new Acl()
                    .setPrincipalType(Role.class.getSimpleName().toLowerCase()).setPrincipalId(roleId)
                    .setResourceType(Menu.class.getSimpleName().toLowerCase()).setResourceGroup(resourceGroup)
                    .setAclCode(aclCode);
                acls.add(acl);
            }
        }
        if (ValidUtil.isValid(operIds)) {
            List<Oper> opers = this.operService.getByIds(operIds);
            Map<String, Integer> aclCodes = new HashMap<String, Integer>();
            for (Oper oper : opers) {
                if (aclCodes.containsKey(oper.getResourceGroup())) {
                    Integer old = aclCodes.get(oper.getResourceGroup());
                    aclCodes.put(oper.getResourceGroup(), old | oper.getAclCode());
                } else {
                    aclCodes.put(oper.getResourceGroup(), oper.getAclCode());
                }
            }
            for (String resourceGroup : aclCodes.keySet()) {
                Integer aclCode = aclCodes.get(resourceGroup);
                Acl acl = new Acl()
                    .setPrincipalType(Role.class.getSimpleName().toLowerCase()).setPrincipalId(roleId)
                    .setResourceType(Oper.class.getSimpleName().toLowerCase()).setResourceGroup(resourceGroup)
                    .setAclCode(aclCode);
                acls.add(acl);
            }
        }
        this.aclService.deleteByRoleId(roleId);
        this.aclService.batchAdd(acls);
        
        return new JsonResult(acls);
    }
    
}
